home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 4 / The 640 Meg Shareware Studio CD-ROM Volume IV (Data Express)(1994).ISO / clang / 131_01.zip / ALEX.C < prev    next >
C/C++ Source or Header  |  1993-06-05  |  8KB  |  386 lines

  1. /*
  2.     ************************************************************
  3.                   ACRL Scanner
  4.     ************************************************************
  5.  
  6.     W. Lemiszki                      9 Jan 1982
  7.  
  8.     Filename: alex.c                 BDS C v1.50
  9. */
  10.  
  11. #include "acrl.h"
  12.  
  13. /*
  14.     Scans the next token from the current line, stores the
  15.     token in tokbuf, and sets the global variables 'class', 'type',
  16.     'value', and 'reloc'.  For ASCII character tokens, 'type' is
  17.     the ASCII code.
  18. */
  19.  
  20. scan()
  21. {
  22. L1:    value = reloc = 0;
  23.  
  24.     while ((type = *lptr++) == ' '  ||    /* skip spaces */
  25.         type == '\t' ||            /* tabs */
  26.         type == '\f'   )        /* and formfeeds */
  27.         ;
  28.  
  29.     if (type == '\n'  ||  type == ';')
  30.         {
  31.         lptr--;                /* never scan past EOL */
  32.         class = EOL;
  33.         return;
  34.         }
  35.  
  36.     switch (class = cclass(type))
  37.         {
  38.         case 0:                /* Illegal character */
  39.         error('I');
  40.         goto L1;            /* scan next */
  41.  
  42.         case 'A':                /* Identifier */
  43.         identifier();
  44.         break;
  45.  
  46.         case '1':                /* Number */
  47.         number();
  48.         break;
  49.  
  50.         case '$' :                /* String */
  51.         string();
  52.         break;
  53.  
  54.         default:                /* 1 char token */
  55.         break;
  56.         }
  57. }
  58.  
  59.  
  60.  
  61.  
  62. /*
  63.  *    Scan an identifier
  64.  *    ------------------
  65.  */
  66. identifier()
  67. {
  68.     idn();                    /* ident to tokbuf */
  69.     if (look(tokbuf))            /* defined ? */
  70.         {
  71.         class = id->clas;
  72.         type = id->typ;
  73.         value = id->val;
  74.         }
  75.         else                /* undefined */
  76.         {
  77.         class = IDENT;
  78.         type = idUND;
  79.         }
  80.     if (type & RELBIT)            /* relocatable ? */
  81.         {
  82.         type ^= RELBIT;            /* turn bit off */
  83.         reloc = TRUE;            /* set global */
  84.         }
  85. }
  86.  
  87.  
  88.  
  89. /* Copy chars into 'tokbuf' until non-alphanumeric */
  90. idn()
  91. {
  92.     char cc, *ptr;
  93.  
  94.     ptr = tokbuf;                /* move into token buffer */
  95.     do {
  96.         *ptr++ = toupper(type);
  97.         } while ((cc=cclass(type=*lptr++)) == 'A' || cc == '1');
  98.     lptr--;                    /* backup */
  99.     *ptr = EOS;
  100. }
  101.  
  102.  
  103.  
  104. /* Check the symbol tables */
  105. int look(s)
  106. char *s;
  107. {
  108.     if (lookup(RESVD, s))            /* reserved word ? */
  109.         return TRUE;
  110.     if (infunc  &&  lookup(LOCAL, s))    /* local symbol ? */
  111.         return TRUE;
  112.     if (lookup(GLOBAL, s))            /* global symbol ? */
  113.         return TRUE;
  114.     if (!infunc  &&  lookup(FUNCS, s))    /* function name ? */
  115.         return TRUE;
  116.     return FALSE;
  117. }
  118.  
  119.  
  120.  
  121.  
  122. /*
  123.  *    Scan a number
  124.  *    -------------
  125.  */
  126. number()
  127. {
  128.     char c, *ptr;
  129.     int radix;
  130.  
  131.     value = 0;                /* init */
  132.     radix = 10;
  133.  
  134.     idn();                    /* ident to tokbuf */
  135.     for (ptr=tokbuf; *++ptr; )        /* scan to end of string */
  136.         ;
  137.     c = *--ptr;                /* get last char */
  138.     *ptr = EOS;                /* erase it */
  139.     switch (c)                /* check if radix char */
  140.         {
  141.         case 'H':  radix = 16;  break;
  142.         case 'D':  radix = 10;  break;
  143.         case 'Q':
  144.         case 'O':  radix =  8;  break;
  145.         case 'B':  radix =  2;  break;
  146.         default :  *ptr = c;        /* no, put it back */
  147.         }
  148.  
  149.     for (ptr = tokbuf;  c = *ptr++; )    /* convert tokbuf */
  150.         {
  151.         if ((c -= '0') > 9)        /* ascii to bcd */
  152.             c -= 7;
  153.         if (c >= radix)
  154.             error ('I');
  155.         value = value * radix + c;
  156.         }
  157.  
  158.     class = OPERAND;
  159.     type = NUMBER;
  160. }
  161.  
  162.  
  163.  
  164.  
  165. /*
  166.  *    Scan a quoted string
  167.  *    --------------------
  168.  *    From input buffer into 'tokbuf'
  169.  */
  170. string()
  171. {
  172.     char c, *ptr;
  173.  
  174.     for (ptr=tokbuf;  (c=*lptr) != '\n';  )
  175.         {
  176.         lptr++;
  177.         if (c == '\'')            /* quote ? */
  178.         if (*lptr == '\'')        /* double quote ? */
  179.             lptr++;            /* just move 1 */
  180.           else
  181.             break;            /* delim */
  182.         *ptr++ = c;
  183.         }
  184.     *ptr = EOS;                /* terminate string */
  185.     class = STRING;
  186. }
  187.  
  188.  
  189.  
  190.  
  191. /*
  192.     CHARACTER CLASSES
  193.  
  194.     Tokens are scanned based on their 1st character.  The following
  195.     values (from cctab[]) indicate that further action is necessary
  196.     to complete scanning this token.  Otherwise it's a 1 char token,
  197.     and cclass returns its token class. Its type is its ASCII code.
  198.      0  -    illegal character
  199.     'A' -    first char of identifier
  200.     '1' -    first char of number
  201.     '$' -    string delimitter (')
  202. */
  203.  
  204. /* Return character class */
  205. byte cclass(c)
  206. char c;
  207. {
  208.     if (c < 128)
  209.         return (cctab[c]);        /* from table */
  210.         else
  211.         return (0);            /* illegal */
  212. }
  213.  
  214.  
  215.  
  216. /*
  217.  *    Init the character class table
  218.  *    ------------------------------
  219.  */
  220. initctab()
  221. {
  222.     setmem(cctab, 128, 0);            /* fill with zeros */
  223.  
  224.     setmem(&cctab['A'], 26, 'A');        /* upper case letters */
  225.     setmem(&cctab['a'], 26, 'A');        /* lower case letters */
  226.     cctab['?'] = 'A';
  227.     cctab['@'] = 'A';
  228.  
  229.     setmem(&cctab['0'], 10, '1');        /* digits */
  230.  
  231.     cctab['\''] = '$';            /* quote */
  232.  
  233.     cctab[':'] = PSEUDO;
  234.     cctab['*'] = OPERATOR;
  235.     cctab['+'] = OPERATOR;
  236.     cctab['-'] = OPERATOR;
  237.     cctab['/'] = OPERATOR;
  238.     cctab['$'] = OPERAND;
  239.     cctab['('] = OPERAND;
  240.     cctab[')'] = MISC;
  241.     cctab[','] = MISC;
  242. }
  243.  
  244.  
  245.  
  246.  
  247. /*
  248.     SYMBOL TABLE ROUTINES
  249.  
  250.     Symbols are stored as linked lists of 'entry's, with the head
  251.     of each list stored in the 'roots[]' array.  To speed up access
  252.     of reserved words, 256 lists are allocated for this table, and
  253.     a simple hash function is used to select the list for any word.
  254. */
  255.  
  256.  
  257. /*
  258.  *    Lookup an identifier in a table
  259.  *    -------------------------------
  260.  *    If found, the global pointer 'id' is left pointing to
  261.  *    the entry.
  262.  */
  263. int lookup(level, str)
  264. int level;                    /* which table to use */
  265. char *str;                    /* ptr to ident string */
  266. {
  267.     if (level == RESVD)            /* reserved word ? */
  268.         level += hash(str);
  269.     if (level == LOCAL)            /* local symbol ? */
  270.         level += numfunc;
  271.  
  272.     for (id = roots[level];  id != NULL;  id = id->next)
  273.         if (strcmp(str, id->nam) == 0)
  274.             return TRUE;
  275.     return FALSE;
  276. }
  277.  
  278.  
  279.  
  280. /* Hash function:  sum the chars */
  281. byte hash(str)
  282. char *str;                    /* ident string */
  283. {
  284.     int i;
  285.  
  286.     for (i=0;  *str;  i += *str++)        /* sum up the chars */
  287.         ;
  288.     return (i & 255);            /* mod 256 */
  289. }
  290.  
  291.  
  292.  
  293.  
  294. /*
  295.  *    Add a symbol into a table
  296.  *    -------------------------
  297.  *    This function assumes the identifier name is static or
  298.  *    already strsav()'d.
  299.  */
  300. install(level, name, class, type, value)
  301. int level;                    /* the table to use */
  302. char *name;                    /* the identifier string */
  303. byte class;                    /* the symbol's class */
  304. byte type;                    /* the symbol's type */
  305. int  value;                    /* the symbol's value */
  306. {
  307.     char *alloc();
  308.  
  309.     id = alloc(sizeof(*id));        /* first make an entry */
  310.     id->nam = name;                /* store parameters */
  311.     id->clas = class;
  312.     id->typ = type;
  313.     id->val = value;
  314.  
  315.     if (level == RESVD)            /* reserved word ? */
  316.         level += hash(name);
  317.     if (level == LOCAL)            /* local symbol ? */
  318.         level += numfunc;
  319.  
  320.     id->next  =  roots[level];        /* add to head of list */
  321.     roots[level]  =  id;
  322. }
  323.  
  324.  
  325.  
  326. /* Save a string in upper memory */
  327. char *strsave(s)
  328. char *s;                    /* string pointer */
  329. {
  330.     char *p;
  331.  
  332.     p = alloc(strlen(s) + 1);        /* get memory */
  333.     strcpy(p, s);                /* move string */
  334.     return (p);
  335. }
  336.  
  337.  
  338. /* Allocate memory */
  339. char *alloc(n)
  340. int n;                        /* number of bytes */
  341. {
  342.     char *p, *sbrk();
  343.  
  344.     if ((p=sbrk(n)) == ERROR)
  345.         fatal("Out of memory\n");
  346.     return (p);
  347. }
  348.  
  349.  
  350.  
  351.  
  352. /*
  353.  *    Init the symbol tables
  354.  *    ----------------------
  355.  */
  356. initsymb()
  357. {
  358.     int i;
  359.  
  360.     for (i = 0;  i < ROOTSIZ;  ++i)        /* init all lists empty */
  361.         roots[i] = NULL;
  362.  
  363.     install(RESVD,    "AND",        OPERATOR,    opAND,    0);
  364.     install(RESVD,    "OR",        OPERATOR,    opOR,    0);
  365.     install(RESVD,    "XOR",        OPERATOR,    opXOR,    0);
  366.     install(RESVD,    "HIGH",        OPERAND,    opHIGH,    0);
  367.     install(RESVD,    "LOW",        OPERAND,    opLOW,    0);
  368.     install(RESVD,    "SHL",        OPERATOR,    opSHL,    0);
  369.     install(RESVD,    "SHR",        OPERATOR,    opSHR,    0);
  370.     install(RESVD,    "MOD",        OPERATOR,    opMOD,    0);
  371.     install(RESVD,    "NOT",        OPERAND,    opNOT,    0);
  372.  
  373.     install(RESVD,    "DB",        PSEUDO,    psDB,    0);
  374.     install(RESVD,    "DS",        PSEUDO,    psDS,    0);
  375.     install(RESVD,    "DW",        PSEUDO,    psDW,    0);
  376.     install(RESVD,    "END",        PSEUDO,    psEND,    0);
  377.     install(RESVD,    "EQU",        PSEUDO,    psEQU,    0);
  378.     install(RESVD,    "SET",        PSEUDO,    psSET,    0);
  379.     install(RESVD,    "FUNCTION", PSEUDO,    psFUNC,    0);
  380.     install(RESVD,    "FEND",        PSEUDO,    psFEND,    0);
  381.     install(RESVD,    "INCLUDE",  PSEUDO,    psINCL,    0);
  382. }
  383.  
  384.  
  385. /*EOF*/
  386.